﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using LinFu.AOP.Interfaces;

namespace BrainTechLLC
{
	public class SecurityRestrictionWrapper : AroundMethodBase, IAroundInvoke
	{
		protected override void Execute(IInvocationContext context, CutpointType when, object returnValue)
		{
			object thisObject = context.Target;
			SecurityRestrictionAttribute[] attrs = context.TargetMethod.ReadAttribute<SecurityRestrictionAttribute>();

			if (when == CutpointType.Before)
			{
				try
				{
					attrs.ForEachAttribute(attr => attr.DoWorkBefore(context, thisObject));
				}
				catch
				{
					SetInterceptionDisabledFlag(context, true);
					throw;
				}
			}
		}

		public override void AfterInvoke(IInvocationContext context, object returnValue)
		{
			if (context.ExtraInfo != null)
				RestoreIsInterceptionDisabledFlag(context);
		}

		private void RestoreIsInterceptionDisabledFlag(IInvocationContext context)
		{
			IModifiableType mod = context.Target as IModifiableType;

			// Set the flag back to its original (pre-method-call) value
			mod.IsInterceptionDisabled = Convert.ToBoolean(context.ExtraInfo);

			// Blank out ExtraInfo to mark that we're done using it
			context.ExtraInfo = null;
		}

		private void SetInterceptionDisabledFlag(IInvocationContext context, bool value)
		{
			IModifiableType mod = (context.Target as IModifiableType);

			// Store the old value of the IsInterceptionDisabled flag
			context.ExtraInfo = mod.IsInterceptionDisabled;

			// Mark that we do not want to execute the original method's code
			mod.IsInterceptionDisabled = value;
		}
	}
}

